﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Cofe.Core.Utils
{
    public static class TaskUtils
    {
        //http://stackoverflow.com/questions/7472013/how-to-create-a-thread-task-with-a-continuous-loop
        public static Task Repeat(TimeSpan pollInterval, Action<CancellationToken> action, 
            CancellationToken token, Action<Exception> onException = null, Action onCancelled = null)
        {
            // We don't use Observable.Interval:
            // If we block, the values start bunching up behind each other.
            return Task.Factory.StartNew(
                () =>
                {
                    for (; ; )
                    {
                        if (token.WaitCancellationRequested(pollInterval))
                        {
                            if (onCancelled != null)
                                onCancelled();
                            break;
                        }

                        try
                        {
                            action(token);
                        }
#if !NETFX_CORE
                        catch (ThreadAbortException)
                        {
                            if (onCancelled != null)
                                onCancelled();
                        }
#endif
                        catch (Exception ex)
                        {
                            if (onException != null)
                                onException(ex);
                            else throw ex;
                        }
                    }
                }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
        }
    }

    static class CancellationTokenExtensions
    {
        public static bool WaitCancellationRequested(
            this CancellationToken token,
            TimeSpan timeout)
        {
            return token.WaitHandle.WaitOne(timeout);
        }
    }
}
